<?php
/**
 * CodeIgniter Model Class
 * @author	Gustavo  Delgado Rodriguez.
 * @version     1.0
 */
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
class Onecore_Model extends CI_Model {
    /*
     * Argumentos de herencia
     */
    protected $_name;               //table name
    protected $_itemName;           //nombre del item
    protected $_validations;        //validations array
    protected $_dbo;                //instancia del objeto db para hacer querys
    protected $_id;                 //pd id de tabla mantenedora
    protected $_fields;                 //pd id de tabla mantenedora
    protected $_fieldsConditions;                 //arreglo de condiciones por columna
    protected $_queryFail;
    protected $_queryErrorMessage;
    protected $_queryErrorNumber;
    protected $_simpleErrorMessage;
    protected $_lastInsertedId;       //id asociado a la ultima insercion

    public $_lastQuery;
    /**
     * Constructor
     *
     * @access public
     */
    function __construct() {
        log_message('debug', "Model Class Initialized");
    }
    function getValidations() {
        return $this->_validations;
    }
    function getQueryFail() {
        return $this->_queryFail;
    }
    function getQueryErrorMessage() {
        return $this->_queryErrorMessage;
    }
    function getQueryErrorNumber() {
        return $this->_queryErrorNumber;
    }
    function getErrorMessage() {
        return "Error(" . $this->_queryErrorNumber . ") " . $this->_queryErrorMessage;
    }
    function getItemName() {
        return $this->_itemName;
    }
    function getIdName() {
        return $this->_id;
    }
    function getTableName() {
        return $this->_name;
    }
    function getLastInsertedId() {
        return $this->_lastInsertedId;
    }
    function getLastQuery(){
        return $this->_lastQuery;
    }
    function getFieldsConditions() {
        return $this->_fieldsConditions;
    }
    function getFields() {
        return $this->_fields;
    }
    private function _cleanArray($array){
        foreach($array as $key=>$value){
            if($key !== 'Data')
                $array[$key] = htmlspecialchars($value);
        }
        return $array;
    }
    function isValidInsert($res) {
        $this->_queryFail = false;
        if (!$res) {
            $this->_queryFail = true;
            $this->_queryErrorMessage = $this->db->_error_message();
            $this->_queryErrorNumber = $this->db->_error_number();
            log_message('error', 'MODIFICACION: Insertar registro de ' .
                    $this->_name . '- operacion erronea, detalle: ' . $this->_queryErrorMessage .
                    ', SQL: ' . $this->db->last_query());
        } else {
            log_message('info', 'MODIFICACION: Insertar registro de ' .$this->_name . '- operacion exitosa');
        }

        return !$this->_queryFail;
    }
    public function save($data, $edit=false) {
        $result = false;
        $str = "";
        if (!empty($data['data'])) {
            if (!$edit) {  //nuevo item
                $str = $this->db->insert_string($this->_name, $this->_cleanArray($data['data']));
                $res = $this->db->query($str);

//                log_message("error",$str);

                $this->_lastInsertedId = $this->db->insert_id();
                $result = $this->isValidInsert($res);
            } else {       //editar item
                if(!empty($data['id'])){

                    //$data['data'] = $this->_cleanArray($data['data']);

                    $dataId = $data['id']; //obtenemos lista pk a buscar wn WHERE
                    $dataUpdate = $data['data'];  //arreglo con parametros a modificar
                    foreach ($this->_id as $id){
                        if(!empty($dataId[$id]))
                            $this->db->where($id, $dataId[$id]);
                        else{
                            $this->_queryFail = true;
                            $this->_queryErrorMessage = "Identificador vacio";
                            $result = false;
                            return false;
                        }
                    }
                    $this->db->update($this->_name, $dataUpdate);
                    $this->_lastQuery = $this->db->last_query();
                    
                    if ($this->db->affected_rows() >= 0) {
                        $result = true;
                    } else {
                        $this->_queryFail = true;
                        $this->_queryErrorMessage = $this->db->_error_message();
                        $this->_queryErrorNumber = $this->db->_error_number();
                        log_message('error', 'MODIFICACION: Actualizar registro de ' .
                                $this->_name . '- operacion erronea, detalle: ' . $this->_queryErrorMessage .
                                ', numero error: ' . $this->_queryErrorNumber . ' SQL: ' . $this->db->last_query());
                        if (empty($this->_queryErrorMessage))
                            $this->_queryErrorMessage = 'Error desconocido.';

                        $result = false;
                    }
                }
                else{
                    $this->_queryFail = true;
                    $this->_queryErrorMessage = "Identificador invalido para editar registro";
                    $result = false;
                    return false;
                }
            }
        }
        else {
            $this->_queryFail = true;
            $this->_queryErrorMessage = 'Sin datos para crear o modificar';
            $this->_queryErrorNumber = '0';
            log_message('error', 'MODIFICACION: Insertar/Actualizar registro de ' .
                    $this->_name . '- operacion erronea, detalle: ' . $this->_queryErrorMessage);
        }
        return $result;
    }
    public function del($data) {
        $result = false;
        //log_message('info', 'MODIFICACION: Eliminar - registro de ' . $this->_name);
        if (!empty($data['id']) || !empty($data) ) {
            
            foreach ($data as $key=>$value) {
                $this->db->where($key, $value);
                //log_message('info', 'MODIFICACION: Eliminar - Filtrando por ' . $id . ' = ' . $dataId[$id]);
            }
//            
//            $dataId = $data['id'];
//            foreach ($this->_id as $id) {
//                $this->db->where($id, $dataId[$id]);
//                log_message('info', 'MODIFICACION: Eliminar - Filtrando por ' . $id . ' = ' . $dataId[$id]);
//            }
            $this->db->delete($this->_name);
            if ($this->db->affected_rows() > 0) {
                $result = true;
                log_message('info', 'MODIFICACION: Eliminar - operacion exitosa');
            } else {
                $this->_queryFail = true;
                $this->_queryErrorMessage = $this->db->_error_message();
                $this->_queryErrorNumber = $this->db->_error_number();
                $result = false;
                log_message('error', 'MODIFICACION: Eliminar - operacion erronea, detalle: ' .
                        $this->db->_error_message() . ', SQL: ' . $this->db->last_query());
            }
        } else {
            log_message('error', 'MODIFICACION: Eliminar - operacion erronea, detalle: sin identificador para eliminar');
            $this->_queryFail = true;
            $this->_queryErrorMessage = 'Sin identificador para eliminar';
            $this->_queryErrorNumber = '0';
        }
        return $result;
    }
    public function delete($data) {
        $result = false;
        log_message('info', 'MODIFICACION: Eliminar - registros de ' . $this->_name);
        if (!empty($data['id'])) {
            $dataId = $data['id'];

            foreach ($dataId as $key => $value) {
                $this->db->where($key, $value);
            }
            $this->db->delete($this->_name);
            if ($this->db->affected_rows() >= 0) {
                $result = true;
                log_message('error', 'MODIFICACION: Eliminar - operacion exitosa');
            } else {
                $this->_queryFail = true;
                $this->_queryErrorMessage = $this->db->_error_message();
                $this->_queryErrorNumber = $this->db->_error_number();
                $result = false;
                log_message('error', 'MODIFICACION: Eliminar - operacion erronea, detalle: ' .
                        $this->db->_error_message() . ', SQL: ' . $this->db->last_query());
            }
        } else {
            log_message('error', 'MODIFICACION: Eliminar - operacion erronea, detalle: sin identificador para eliminar');
            $this->_queryFail = true;
            $this->_queryErrorMessage = 'Sin identificador para eliminar';
            $this->_queryErrorNumber = '0';
        }
        return $result;
    }
    public function loadGrid_old($limit, $start, $conditions, $order,$selected) {
        if(!empty ($selected) && $selected!==null){
            $this->db->select(implode(',', $selected), FALSE);
        }
        else{
            $this->db->select("*", FALSE);
        }
        $arr = array();
        $this->db->from($this->_name);
        if ($conditions !== null) {
            $this->db = $this->setConditions($conditions);
        }
        if ($order !== null) {
            $this->db->order_by($order['field'], $order['direction']);
        }
        if ($limit !== "" && $start !== "") {
            $this->db->limit($limit, $start);
        }
        $query = $this->db->get();
        foreach ($query->result() as $obj) {
            $arr[] = $obj;
        }
        $res = array(
            'results' => $this->getCountByFilters($conditions),
            'items' => $arr
        );
        return $res;
    }
    public function loadGrid($limit, $start, $conditions, $order,$selected=null,$from=null,$defaultValue=array()) {
        $arr = array();
        $validateFields = true;
        $from2 = "";
        if(!empty ($selected) && $selected!==null){
            /*
             * creamos select con t1 tabla modelo, t2, t3, .. tablas para join 
             */
            $foreignColumns = implode(',', $selected);
            $this->db->select($foreignColumns,FALSE);
            $validateFields = false;
        }
        else{
            $this->db->select("*", FALSE);
        }
        if(!empty ($from) && $from!==null){//se arma query usando otras tablas
            $this->db->from($this->_name.' t1, '.$from);

            $validateFields = false;
        }
        else{
            $this->db->from($this->_name);
        }
        if ($conditions !== null) {
            $this->db = $this->setConditions($conditions,$validateFields);
        }
        if ($order !== null) {
            $this->db->order_by($order['field'], $order['direction']);
        }
        if (!empty($limit) && !empty($start)) {
            $this->db->limit($limit, $start);
        }
        $query = $this->db->get();
        $this->_lastQuery = $this->db->last_query();

	//echo $this->db->last_query();exit;

        log_message('info', "query load: ".$this->_lastQuery);

        if(!empty($defaultValue)){ //para filas tipo --TODOS--
            $arr[] = $defaultValue;
        }
        foreach ($query->result() as $obj) {
            $arr[] = $obj;
        }
        $nTotal = 0;
        if($validateFields){
            $nTotal = $this->getCountByFilters($conditions);
        }
        else{
            $customFrom = $this->_name.' t1, '.$from;
            $nTotal = $this->countByCondisionsJoin($customFrom,$conditions);
        }
/*
        $res = array(
            'results' => $nTotal,
            'items' => $arr
        );
 * 
 * 
 */
        $res = array(
            'results' => $nTotal,
            'items' => $arr
        );
        return $res;
    }
    function countByCondisionsJoin($from, $conditions){
        $this->setConditions($conditions, false);
        $this->db->from($from);
        $results = $this->db->count_all_results();
        return $results;
    }
    function getItem($conditions, $selected,$from=null){
        $validateFields = true;
        if(!empty ($selected) && $selected!==null){
            $this->db->select(implode(',', $selected), FALSE);
            $validateFields = false;
        }
        else{
            $this->db->select("*", FALSE);
        }
        $arr = array();
        if(!empty ($from) && $from!==null){//se arma query usando otras tablas
            $this->db->from($this->_name.' t1, '.$from);
            $validateFields = false;
        }
        else{
            $this->db->from($this->_name);
        }
        if ($conditions !== null) {
            $this->db = $this->setConditions($conditions,$validateFields);
        }
        $query = $this->db->get();

        $this->_lastQuery = $this->db->last_query();
          
        foreach ($query->result() as $obj) {
            $arr[] = $obj;
        }
        $res = $this->getHiddenId($arr[0]);
        return $res;
    }
    function listEntities($cfg){
        $res = array();
        if(!empty ($cfg->selected) && $cfg->selected!==null){
            $this->db->select(implode(',', $cfg->selected), FALSE);
        }
        else{
            $this->db->select("*", FALSE);
        }
        if (!empty($cfg->conditions) && $cfg->conditions !== null) {
            $this->db = $this->setFilters($cfg->conditions);
        }
        $this->db->from($this->_name);
        if (!empty($cfg->orderField) && $cfg->orderField !== null) {
            $this->db->order_by($cfg->orderField, $cfg->orderDirection);
        }

        if (!empty($cfg->limit)) {
            $this->db->limit($cfg->limit, $cfg->start);
        }

        $query = $this->db->get();
        $this->_lastQuery = $this->db->last_query();

        //echo $this->_lastQuery;exit;

        $arr = $query->result();


        if (!empty($cfg->conditions) && $cfg->conditions !== null)
            $results = $this->countByFilters($cfg->conditions);
        else
            $results = count($arr);

        $res = array(
            'results' => $results,
            'sql'=>$this->_lastQuery,
            'items' => $arr
        );
        return $res;
    }
    function loadList($order,$selected,$conditions,$defaultValue=array()){
        $res = array();
        if(!empty ($selected) && $selected!==null){
            $this->db->select(implode(',', $selected), FALSE);
        }
        else{
            $this->db->select("*", FALSE);
        }
        if ($conditions !== null) {
            $this->db = $this->setConditions($conditions);
        }
        $this->db->from($this->_name);
        if ($order !== null) {
            $this->db->order_by($order['field'], $order['direction']);
        }
        $query = $this->db->get();
        $this->_lastQuery = $this->db->last_query();
        
//        log_message("error","sql: ".$this->_lastQuery);
        
        $results = $this->getCountByFilters($conditions);//$this->db->count_all($this->_name);
        $arr = array();

        if(!empty($defaultValue)){ //para filas tipo --TODOS--
            $arr[] = $defaultValue;
        }

        foreach ($query->result() as $obj) {
            $arr[] = $obj;
        }
        $res = array(
            'results' => $results,
            'items' => $arr
        );
        return $res;
    }
    function getItemBasic($conditions, $selected){
        if(!empty ($selected) && $selected!==null){
            $this->db->select(implode(',', $selected), FALSE);
        }
        else{
            $this->db->select("*", FALSE);
        }
        $arr = array();
        $this->db->from($this->_name);
        if ($conditions !== null) {
            $this->db = $this->setConditions($conditions);
        }
        $query = $this->db->get();
        foreach ($query->result() as $obj) {
            $arr[] = $obj;
        }
 //       $res = $this->getHiddenId($arr[0]);
        return $arr[0];
    }
    public function getHiddenId($obj){
        foreach($this->_id as $id){
            $argument = '_'.$id;
            $obj->$argument = $obj->$id;
        }
        return $obj;
    }
    public function getError() {
        switch ($this->_queryErrorNumber) {
            case '1062':
                $this->_simpleErrorMessage = 'Error de duplicidad. Ya existe un registro con los datos proporcionados. ';
                break;
            case '1452':
                $this->_simpleErrorMessage = 'No se puede actualizar, relación inválida en el identicador.';
                break;
            case '1451':
                $this->_simpleErrorMessage = 'El registro a modificar esta siendo usado por otros elementos.';
                break;
            case '0':
                $this->_simpleErrorMessage = $this->_queryErrorMessage;
                break;
            /*case '-1':
                $this->_simpleErrorMessage = $this->_simpleErrorMessage;
            break;*/
            default:
                $this->_simpleErrorMessage = $this->getErrorMessage();
                break;
        }
        return $this->_simpleErrorMessage;
    }
    public function array_to_object($array = array()) {
        return (object) $array;
    }
    public function getCountByFilters($conditions) {
        $results = 0;
        foreach ($conditions as $condition) {
            if (in_array($condition['field'], $this->_fields)) {
                switch ($condition['type']) {
                    case 'where':$this->db->where($condition['field'], $condition['value']);
                        break;
                    case 'or_where':$this->db->or_where($condition['field'], $condition['value']);
                        break;
                    case 'where_in':$this->db->where_in($condition['field'], $condition['value']);
                        break;
                    case 'or_where_in':$this->db->or_where_in($condition['field'], $condition['value']);
                        break;
                    case 'where_not_in':$this->db->where_not_in($condition['field'], $condition['value']);
                        break;
                    case 'or_where_not_in':$this->db->or_where_not_in($condition['field'], $condition['value']);
                        break;
                    case 'like':$this->db->like($condition['field'], $condition['value']);
                        break;
                    case 'or_like':$this->db->or_like($condition['field'], $condition['value']);
                        break;
                    case 'not_like':$this->db->not_like($condition['field'], $condition['value']);
                        break;
                    case 'or_not_like':$this->db->or_not_like($condition['field'], $condition['value']);
                        break;
                }
            }
        }
        $this->db->from($this->_name);

        $results = $this->db->count_all_results();
        return $results;
    }
    public function setFilters($conditions) {
        foreach ($conditions as $key=>$value) {
            if($value!="")
                $this->db->where($key." = '$value'");
        }
        return $this->db;
    }
    public function countByFilters($conditions) {
        $results = 0;
        foreach ($conditions as $key=>$value) {
            if(!empty($value))
                $this->db->where($key, $value);
        }
        $this->db->from($this->_name);
        $results = $this->db->count_all_results();
        return $results;
    }
    public function setConditions($conditions, $validate=true) {
        if($validate){
            foreach ($conditions as $condition) {
                if (in_array($condition['field'], $this->_fields)) {
                    switch ($condition['type']) {
                        case 'where':$this->db->where($condition['field'], $condition['value']);
                            break;
                        case 'or_where':$this->db->or_where($condition['field'], $condition['value']);
                            break;
                        case 'where_in':$this->db->where_in($condition['field'], $condition['value']);
                            break;
                        case 'or_where_in':$this->db->or_where_in($condition['field'], $condition['value']);
                            break;
                        case 'where_not_in':$this->db->where_not_in($condition['field'], $condition['value']);
                            break;
                        case 'or_where_not_in':$this->db->or_where_not_in($condition['field'], $condition['value']);
                            break;
                        case 'like':$this->db->like($condition['field'], $condition['value']);
                            break;
                        case 'or_like':$this->db->or_like($condition['field'], $condition['value']);
                            break;
                        case 'not_like':$this->db->not_like($condition['field'], $condition['value']);
                            break;
                        case 'or_not_like':$this->db->or_not_like($condition['field'], $condition['value']);
                            break;
                    }
                }
            }
        }
        else{
            foreach ($conditions as $condition) {
                /*
                 * Si posee "." significa que es una condicion tabla.columna, en caso contrario se asumira como texto
                 */
                if(strpos($condition['value'], ".") !== FALSE)
                    $value = $condition['value'];
                else
                    $value = "'".$condition['value']."'";
                switch ($condition['type']) {
                    case 'where':$this->db->where($condition['field']." = ".$value);
                        break;
                    case 'or_where':$this->db->or_where($condition['field'],$value);
                        break;
                    case 'where_in':$this->db->where_in($condition['field'], $condition['value']);
                        break;
                    case 'or_where_in':$this->db->or_where_in($condition['field'], $condition['value']);
                        break;
                    case 'where_not_in':$this->db->where_not_in($condition['field'], $condition['value']);
                        break;
                    case 'or_where_not_in':$this->db->or_where_not_in($condition['field'], $condition['value']);
                        break;
                    case 'like':$this->db->like($condition['field'], $condition['value']);
                        break;
                    case 'or_like':$this->db->or_like($condition['field'], $condition['value']);
                        break;
                    case 'not_like':$this->db->not_like($condition['field'], $condition['value']);
                        break;
                    case 'or_not_like':$this->db->or_not_like($condition['field'], $condition['value']);
                        break;
                }
            }
        }
        return $this->db;
    }
    /*
     * $arguments[0] = nombre de columna o field
     * $arguments[1] = empty o array con columnas a devolver
     */
    public function __call($name, $arguments) {
        $arguments = $arguments[0];
        $findme = 'getBy';
        $pos = strpos($name, $findme);
        $arr = array();
        if ($pos === FALSE || $pos = "" && count($arguments) > 0) {
            return null;
        } else {
            $lengthString = strlen($name);
            $i = strpos($name, 'y') + 1;
            $length = $lengthString - $i;
            $method = substr($name, strpos($name, 'y') + 1, $length);
            //if (in_array($method, $this->_fields)) {
                if (!empty($arguments[1]) && is_array($arguments[1])) {
                    $this->db->select(implode(', ', $arguments[1]));
                } else {
                    $this->db->select("*");
                }
                if(is_array($arguments))    $this->db->where($method, $arguments[0]);
                else    $this->db->where($method, $arguments);
                //echo "campo: $method, argumentos: ".print_r($arguments);

                $this->db->from($this->_name);
                $query = $this->db->get();
                
//                log_message("error",  $this->db->last_query());
                
                foreach ($query->result() as $row) {
                    $arr[] = $row;
                }
            /*} else {
                return null;
            }*/
        }
        return $arr;
    }
    public function toGraphData($var){
        if($var === null) $var = 0;
        else{
            if(empty($var)) $var = 0;
            else $var = (int) intval($var);
        }
        return $var;
    }
}
/* End of file MY_Model.php */
/* Location: ./system/application/libraries/MY_Model.php */